﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Serialization;
using BI = System.Numerics.BigInteger;

namespace PodpisyElektorniczne.Classes
{
    public class Signature
    {
        
        public BI G { get; set; }       //srs
        public BI DashedG { get; set; } //srs
        public BI DashedY { get; set; } //srs
        public BI DashedW { get; set; } //srs
        public List<BI> PublicKeysY { get; set; } //srs
        public List<BI> SaltW { get; set; } //srs
        public List<BI> VectorC { get; set; }//seqdl
        public List<BI> VectorS { get; set; }//seqdl
        public List<Skdl> Skdl { get; set; } //skdl 
        public string Msg { get; set; } //srs
            
        public Signature() { }

        public override string ToString()
        {
            var strY = PublicKeysY.Aggregate(string.Empty, (current, t) => current + t.ToString("R"));
            var strW = SaltW.Aggregate(string.Empty, (current, t) => current + t.ToString("R"));
            var strC = VectorC.Aggregate(string.Empty, (current, t) => current + t.ToString("R"));
            var strS = VectorC.Aggregate(string.Empty, (current, t) => current + t.ToString("R"));
            var strSkdl = Skdl.Aggregate(string.Empty, (current, t ) => current + t.ToString());
            return string.Format("{0}{1}{2}{3}{4}{5}{6}{7}{8}", G, DashedG, DashedY, DashedW.ToString("R"), strY, strW, strC, strS, strSkdl, Msg);
        }
        
        /// <summary>
        /// Procedure to serialize the a signature
        /// List content:
        /// 1. G - generator
        /// 2. dashed G - generator
        /// 3. dashed Y
        /// 4. dashed W
        /// 5. Msg - message
        /// 5. Y - list of used public keys
        /// 6. W - list of sal values
        /// 7.1 VectorC - seqdl
        /// 7.2 VectorS - seqdl
        /// 
        /// </summary>
        /// <param name="path">Path: file localization</param>
        /// <returns></returns>

        public bool ObjSerialization(string path)
        {
            try
            {
                var dic = new List<string[]>
                              {
                                  new []{
                                  G.ToString("R"),
                                  DashedG.ToString("R"),
                                  DashedY.ToString("R"),
                                  DashedW.ToString("R"),
                                  Msg},
                                  PublicKeysY.Select(key => key.ToString("R")).ToArray(), 
                                  SaltW.Select(salt => salt.ToString("R")).ToArray(),
                                  VectorC.Select(c => c.ToString("R")).ToArray(),
                                  VectorS.Select(s => s.ToString("R")).ToArray(),
                                  Skdl.Select(s => s.ToString()).ToArray()
                              };

                var res = false;
                using (var str = new StreamWriter(path))
                {
                    new XmlSerializer(typeof(List<string[]>)).Serialize(str, dic);
                    res = true;
                }
                return res;

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        
        public static Signature ObjDeserializerStat(string path, bool e)
        {
            try
            {
                Signature signature;
                using (var sign = new StreamReader(path))
                {
                    var res = (List<string[]>)(new XmlSerializer(typeof (List<string[]>)).Deserialize(sign));
                    signature = new Signature
                                        {
                                            G = BI.Parse(res[0][0]),
                                            DashedG = BI.Parse(res[0][1]),
                                            DashedY = BI.Parse(res[0][2]),
                                            DashedW = BI.Parse(res[0][3]),
                                            Msg = res[0][4],
                                            PublicKeysY = res[1].Select(BI.Parse).ToList(),
                                            SaltW = res[2].Select(BI.Parse).ToList(),
                                            VectorC = res[3].Select(BI.Parse).ToList(),
                                            VectorS = res[4].Select(BI.Parse).ToList()
                                        };
                }
                return signature;
            }
            catch(Exception)
            {
                throw new Exception(@"There was a problem with key deserialization. Make sure that the key is properly written and try again.");
            }
        }
    }
}